﻿using System;
using System.IO;
using System.Net;
using System.Runtime.CompilerServices;
using TNet;
using UnityEngine;

public class SLobbyClient
{
    public string errorString;
    public bool isActive;
    public ServerList knownServers;
    private TNet.Buffer mBuffer;
    private long mNextSend;
    private bool mReEnable;
    private List<IPEndPoint> mRemoteAddressList;
    private TNet.Buffer mRequest;
    private int mScanEndPort;
    private int mScanStartPort;
    private UdpProtocol mUdp;
    public OnListChange onChange;
    private const long SCAN_TIME = 0xbb8L;

    public SLobbyClient()
    {
        this.errorString = string.Empty;
        this.knownServers = new ServerList();
        this.mScanStartPort = 0x112f;
        this.mScanEndPort = 0x1139;
        this.mUdp = new UdpProtocol();
        this.mRemoteAddressList = new List<IPEndPoint>();
    }

    public SLobbyClient(int startPort, int endPort)
    {
        this.errorString = string.Empty;
        this.knownServers = new ServerList();
        this.mScanStartPort = 0x112f;
        this.mScanEndPort = 0x1139;
        this.mUdp = new UdpProtocol();
        this.mRemoteAddressList = new List<IPEndPoint>();
        this.SetScanPortRange(startPort, endPort);
    }

    public void ApplicationPause(bool paused)
    {
        if (paused)
        {
            if (this.isActive)
            {
                this.mReEnable = true;
                this.Stop();
            }
        }
        else if (this.mReEnable)
        {
            this.mReEnable = false;
            this.Start();
        }
    }

    protected BinaryWriter BeginSend(Packet packet)
    {
        this.mBuffer = TNet.Buffer.Create();
        return this.mBuffer.BeginPacket(packet);
    }

    protected void EndSend(IPEndPoint ip)
    {
        this.mBuffer.EndPacket();
        this.mUdp.Send(this.mBuffer, ip);
        this.mBuffer.Recycle();
        this.mBuffer = null;
    }

    protected virtual bool ProcessOtherPacket(Packet request, BinaryReader reader)
    {
        return false;
    }

    private void ReBuildScanList()
    {
        int num = (this.mScanEndPort - this.mScanStartPort) + 1;
        for (int i = 0; i < num; i++)
        {
            int port = this.mScanStartPort + i;
            IPEndPoint item = new IPEndPoint(IPAddress.Broadcast, port);
            if (item == null)
            {
                this.mUdp.Error(new IPEndPoint(IPAddress.Loopback, this.mUdp.listeningPort), "Invalid Port: " + port);
            }
            else
            {
                this.mRemoteAddressList.Add(item);
            }
        }
    }

    public void SetScanPortRange(int startPort, int endPort)
    {
        this.mScanStartPort = startPort;
        this.mScanEndPort = endPort;
        this.mRemoteAddressList.Clear();
        this.ReBuildScanList();
    }

    public void Start()
    {
        if (this.mRequest == null)
        {
            this.mRequest = TNet.Buffer.Create();
            this.mRequest.BeginPacket(Packet.RequestServerList).Write((ushort) 0x3600);
            this.mRequest.EndPacket();
        }
        if (this.mRemoteAddressList.Count == 0)
        {
            this.ReBuildScanList();
        }
        int num = 3;
        for (int i = 0; i < num; i++)
        {
            if (this.mUdp.Start(Tools.randomPort))
            {
                break;
            }
        }
    }

    public void Stop()
    {
        this.isActive = false;
        this.errorString = string.Empty;
        this.knownServers.Clear();
        try
        {
            this.mUdp.Stop();
            if (this.mRequest != null)
            {
                this.mRequest.Recycle();
                this.mRequest = null;
            }
            if (this.onChange != null)
            {
                this.onChange();
            }
        }
        catch (Exception)
        {
        }
    }

    public void Update()
    {
        TNet.Buffer buffer;
        IPEndPoint point;
        bool flag = false;
        long time = DateTime.UtcNow.Ticks / 0x2710L;
        while ((this.mUdp != null) && this.mUdp.ReceivePacket(out buffer, out point))
        {
            if (buffer.size > 0)
            {
                try
                {
                    BinaryReader reader = buffer.BeginReading();
                    Packet request = (Packet) reader.ReadByte();
                    switch (request)
                    {
                        case Packet.ResponseServerList:
                            this.isActive = true;
                            this.mNextSend = time + 0xbb8L;
                            this.knownServers.ReadFrom(reader, time);
                            this.knownServers.Cleanup(time);
                            flag = true;
                            goto Label_00B7;

                        case Packet.Error:
                            this.errorString = reader.ReadString();
                            Debug.LogWarning(this.errorString);
                            flag = true;
                            goto Label_00B7;
                    }
                    this.ProcessOtherPacket(request, reader);
                }
                catch (Exception)
                {
                }
            }
        Label_00B7:
            buffer.Recycle();
        }
        if (this.knownServers.Cleanup(time))
        {
            flag = true;
        }
        if (flag && (this.onChange != null))
        {
            this.onChange();
        }
        else if ((this.mNextSend < time) && (this.mUdp != null))
        {
            this.mNextSend = time + 0xbb8L;
            int count = this.mRemoteAddressList.Count;
            for (int i = 0; i < count; i++)
            {
                this.mUdp.Send(this.mRequest, this.mRemoteAddressList[i]);
            }
        }
    }

    public delegate void OnListChange();
}

